package com.ddwl.common.dao;

import cn.hutool.core.util.StrUtil;
import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.dao.mapper.TkMapper;
import com.ddwl.common.dao.model.BaseModel;
import com.ddwl.common.dao.model.BaseModelNew;
import com.ddwl.common.util.UUIDGenerator;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.ParameterizedType;
import java.time.Instant;
import java.util.Collection;
import java.util.List;

/**
 * 类TkDao.java的实现描述：基础公共DAO
 *
 * @author zach
 * @Date :2020-06-10 11:02.
 */
public class TkDao<M extends TkMapper<T>, T extends BaseModel> {

    @Autowired
    public M baseMapper;

    private Class<T> tType = null;


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    public T selectByPrimaryKey(String id) {
        T model = baseMapper.selectByPrimaryKey(id);
        if (model != null && BaseEnum.DflagEnum.DELETED.getCode().equals(model.getDflag())) {
            return null;
        }
        return model;
    }

    /**
     * 查询多条数据
     *
     * @param ids
     * @return
     */
    public List<T> selectByPrimaryKeys(Collection<String> ids) {
        Example example = getExample();
        if (!CollectionUtils.isEmpty(ids)) {
            example.and().andIn("id", ids);
        }
        return baseMapper.selectByExample(example);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param model 实例对象
     * @return 对象列表
     */
    public List<T> select(T model) {
        model.setDflag(BaseEnum.DflagEnum.NOT_DELETE.getCode());
        return baseMapper.select(model);
    }

    public List<T> selectAll() {
        T t = getModel();
        t.setDflag(BaseEnum.DflagEnum.NOT_DELETE.getCode());
        return select(t);
    }

    /**
     * 通过实体作为筛选条件查询
     *
     * @param model 实例对象
     * @return 对象列表
     */
    public T selectOne(T model) {
        List<T> list = select(model);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 新增数据
     *
     * @param model 实例对象
     * @return 影响行数
     */
    public void insert(T model) {
        if (StrUtil.isEmpty(model.getId())) {
            model.setId(UUIDGenerator.getShortUUID());
        }
        model.setGmtModified(Instant.now());
        model.setGmtCreated(Instant.now());
        model.setDflag(BaseEnum.DflagEnum.NOT_DELETE.getCode());
        baseMapper.insert(model);
    }

    public int insertList(List<T> models) {
        if (CollectionUtils.isEmpty(models)) {
            return 0;
        }
        for (T model : models) {
            if (StrUtil.isEmpty(model.getId())) {
                model.setId(UUIDGenerator.getShortUUID());
            }
            model.setGmtModified(Instant.now());
            model.setGmtCreated(Instant.now());
            model.setDflag(BaseEnum.DflagEnum.NOT_DELETE.getCode());
        }
        return baseMapper.insertListNoSkipId(models);
    }

    /**
     * 修改数据
     *
     * @param model 实例对象
     * @return 影响行数
     */
    public int updateByPrimaryKeySelective(T model) {
        model.setGmtModified(Instant.now());
        return baseMapper.updateByPrimaryKeySelective(model);
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 影响行数
     */
    public int deleteById(String id) {
        T model = getModel();
        model.setId(id);
        model.setGmtModified(Instant.now());
        model.setDflag(BaseEnum.DflagEnum.DELETED.getCode());
        return updateByPrimaryKeySelective(model);
    }

    public int deleteById(String id, String userId) {
        T model = getModel();
        model.setId(id);
        model.setGmtModified(Instant.now());
        if (model instanceof BaseModelNew) {
            ((BaseModelNew) model).setModifiedUserId(userId);
        }
        model.setDflag(BaseEnum.DflagEnum.DELETED.getCode());
        return updateByPrimaryKeySelective(model);
    }

    @SneakyThrows
    private T getModel() {
        if (tType == null) {
            ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
            tType = (Class<T>) superClass.getActualTypeArguments()[1];
        }
        T model = tType.newInstance();
        return model;
    }

    public Example getExample() {
        Example example = new Example(getType());
        example.and().andEqualTo("dflag", BaseEnum.DflagEnum.NOT_DELETE.getCode());
        return example;
    }

    private Class<T> getType() {
        if (tType == null) {
            ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
            this.tType = (Class<T>) superClass.getActualTypeArguments()[1];
        }
        return this.tType;
    }
}
